/*  
     PlAr is Platform Arena: a 2D multiplayer shooting game
     Copyright (C) 2009 Ragagnin Antonio <spocchio@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package plar.ClientServer;

import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Calendar;

import javax.swing.JOptionPane;

import plar.core.Common;
import plar.core.Game;
import plar.core.Sprite;
import plar.core.Player;

public class  Client {
	private ArrayList <ArrayList <Sprite>> buffer;
    public Boolean busy;
	public Player currentPlayer;
	public Game g;
	ObjectInputStream ois;
	ObjectOutputStream oos;
	public ArrayList<String> premuti;
	public Point resolution;
	Socket socket;
	String _server;
	Integer _port;
	String nick;
	String type;
	boolean isConnected=false;
	public String error;

	public Client() {
		resolution = new Point(800, 600);
		buffer = new ArrayList <ArrayList <Sprite>> ();
		busy = false;
	}

	public boolean close() throws IOException {
		oos.close();
		ois.close();

		socket.close();
		return false;
	}

	public String connect(String server, int port) throws IOException, ClassNotFoundException {
	//	if(busy) return ""; else busy = true;
		
		oos = null;
		ois = null;
		buffer = new ArrayList <ArrayList <Sprite>> ();
		String data;
		socket = null;
		_server=server;
		_port = port;
		try {
			// open a socket connection
			Common.info(1,"Client.connect() " + server + ":" + port);
			socket = new Socket(server, port);
			
			// open I/O streams for objects
			oos = new ObjectOutputStream(socket.getOutputStream());
			ois = new ObjectInputStream(socket.getInputStream());
			// read an object from the server
			data = (String)ois.readObject();
			isConnected=true;
		} catch (Exception e) {
			System.out.println(e);
			data= new String("client: error connecting!");
		}
		// TODO!!!
		socket.setSendBufferSize(4);
		
		resolution = (Point)ois.readObject();
		socket.setTcpNoDelay(true);
		busy = false;
		Common.info(1,"Client.connect(): buffersize="+socket.getSendBufferSize()+"; delay="+socket.getTcpNoDelay()+"; resolution="+resolution);
		
		return data;
	}

	public boolean getOutput() {
		return false;
	}

	public synchronized Rectangle getPlayerPosition() throws IOException, ClassNotFoundException {
	//	if(busy) return null; else busy = true;
		oos.writeInt(Signal.POSITION);
		
		oos.flush();
		int x = ois.readInt();
		int y = ois.readInt();
		int w = ois.readInt();
		int h = ois.readInt();
		return new Rectangle(x,y,w,h);

	}


	public synchronized ArrayList<ShownElement> getScreen() throws IOException, ClassNotFoundException 
		 {
		try{
		long a,r,d;
		boolean active = true;
		oos.writeInt(Signal.UPDATE);
		oos.writeInt(Signal.SCREEN);
		a= Calendar.getInstance().getTimeInMillis();
		
		oos.flush();

	
				
		Integer updates = ois.readInt();

		for(int i = 0;i<updates;i++)
		{
			//Common.info("loop "+i);
			ArrayList <Sprite> o = (ArrayList <Sprite>) ois.readObject();

			buffer.add(o);
			//Common.info("recv "+o);
			
		}
		ArrayList<ShownElement> screen = new ArrayList<ShownElement>();
		ShownElement e;
		
		

		
		
		Integer counter = ois.readInt();
		for(int i = 0;i<counter;i++)
		{
			Integer x = ois.readInt();
			
				Integer y = ois.readInt();
				Integer w = ois.readInt();
				Integer h = ois.readInt();
				Integer b = ois.readInt();
    			//Common.info("proposto i"+buffer.get(b)+" at "+new Rectangle(x,y,h,w));
				e = new ShownElement(new Rectangle(x,y,w,h),buffer.get(b));
				screen.add(e);
		
		}
	//	 JOptionPane.showInputDialog(null,
	//	"Select player: [qeen/squeak] ");

		busy = false;
		return screen;
		}catch(Exception e)
		{
			isConnected=false;
			error = e.getLocalizedMessage();
		}
	
		return null;
	}

	public synchronized boolean sendInput(ArrayList<String> i) {
	//	if(busy) return false; else busy = true;
	try{	
		String premuti= new String();
		for (String s : i) {
			premuti+=s+" ";
		}
	//	Common.info("sended :"+premuti);
		oos.writeInt(Signal.INPUT);
	
		oos.writeObject(new String(premuti));
		oos.flush();
		busy = false;
		return true;
	}catch(Exception e)
	{
		isConnected=false;
		error = e.getLocalizedMessage();
	}
	return false;
	}

	public synchronized boolean setPlayer(String n, String t) throws IOException {

	//	if(busy) return false;			 else busy = true;
		
		
		nick = n;
		type= t;
		oos.writeInt(Signal.PLAYER);
		String s = new String(t+" "+n);
		oos.writeObject(s);
		busy = false;
		return true;
	}
	
		public synchronized String getChat() {

	try{
		oos.writeInt(Signal.GET_MSG);
		oos.flush();

		String s = (String) ois.readObject();
busy = false;
			return s;
		}catch(Exception e)
	{
		isConnected=false;
		error = e.getLocalizedMessage();
		return null;
	}
	
	}
	
	public synchronized boolean chat(String c)  {

try{
		oos.writeInt(Signal.CHAT);
		oos.flush();
		String s = new String(c);
		oos.writeObject(s);
		busy = false;	
		
		}catch(Exception e)
	{
		isConnected=false;
		error = e.getLocalizedMessage();
		return false;
	}
		return true;
	}
	
	public synchronized boolean setDirection(double x,double y)  {

	try{
		oos.writeInt(Signal.DIRECTION);
		oos.writeInt((int)(x*100));
		oos.writeInt((int)(y*100));
		return true;
		}catch(Exception e)
	{
		isConnected=false;
		error = e.getLocalizedMessage();
	}
	return false;
	}
	
	public synchronized boolean getClient()
	{
		if(busy) return false; else busy = true;
		//Common.info("getted");
		return true;
		
	}
	public synchronized boolean dropClient()
	{
		if(busy) return false; else busy = false;
		//Common.info("released");
	
		return true;
	}

	public boolean isConnected() {
		 
		return isConnected;
	}

}
